package com.t2two.example.common.utils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.experimental.UtilityClass;
import net.sourceforge.pinyin4j.PinyinHelper;
//import sun.misc.BASE64Encoder;

import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.hutool.core.codec.Base64.encode;

/**
 * 字符串处理工具类
 */
@UtilityClass
public class StrUtils {

    private volatile static Configuration configuration;

    private static final String CHARACTERS = "ABCDEFGHJKLMNPQRSTUVWXY0123456789";
    private static final SecureRandom RANDOM = new SecureRandom();

    static {
        if (configuration == null) {
            synchronized (StrUtils.class) {
                if (configuration == null) {
                    configuration = new Configuration(Configuration.VERSION_2_3_28);
                }
            }
        }
    }

    /**
     * @return
     * @author : bruce lan/00001
     * @description: 判断两个字符串相似度
     * @date : 2022/2/9 14:15
     */
    public static float getSimilarityRatio(String str, String target) {
        int[][] d; // 矩阵
        int n = str.length();
        int m = target.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0 || m == 0) {
            return 0;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) { // 初始化第一列
            d[i][0] = i;
        }
        for (j = 0; j <= m; j++) { // 初始化第一行
            d[0][j] = j;
        }
        for (i = 1; i <= n; i++) { // 遍历str
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + temp);
            }
        }
        return (1 - (float) d[n][m] / Math.max(str.length(), target.length())) * 100F;
    }

    public static String freemarkerRender(Map<String, Object> dataMap, String ftlFilePath, String ftlFileName) {
        Writer out = new StringWriter();
        configuration.setDefaultEncoding("UTF-8");
        configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        try {
            File file = new File(ftlFilePath);
            configuration.setDirectoryForTemplateLoading(file);
            configuration.setLogTemplateExceptions(false);
            configuration.setWrapUncheckedExceptions(true);
            Template template = configuration.getTemplate(ftlFileName, "UTF-8");
            template.process(dataMap, out);
            out.flush();
            return out.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 图片URL转Base64编码
     *
     * @param imgUrl 图片URL
     * @return Base64编码
     */
    public static String imageUrlToBase64(String imgUrl) {
        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream outStream = null;
        HttpURLConnection httpUrl = null;
        try {
            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();

            is = httpUrl.getInputStream();
            outStream = new ByteArrayOutputStream();

            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用输入流从buffer里把数据读取出来
            while ((len = is.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }

            // 对字节数组Base64编码
            return encode(outStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (outStream != null) {
                    outStream.close();
                }
                if (httpUrl != null) {
                    httpUrl.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     * 图片转字符串
     *
     * @param image 图片Buffer
     * @return Base64编码
     */
//    public static String encode(byte[] image) {
//        BASE64Encoder decoder = new BASE64Encoder();
//        return replaceEnter(decoder.encode(image));
//    }

    /**
     * 字符替换
     *
     * @param str 字符串
     * @return 替换后的字符串
     */
    public static String replaceEnter(String str) {
        String reg = "[\n-\r]";
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(str);
        return m.replaceAll("");
    }


    public String getMd5(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * @author     : bruce lan/00001
     * @description: string转xml时需替换特殊字符
     * @date       : 2022/5/18 19:25
     * @return
     */
    public static String escapeStr(String str) {
        if (null == str) {
            return null;
        }
        // 转换特殊字符
        String ds = str.replace("&", "&amp;");
        ds = ds.replace("<", "&lt;");
        ds = ds.replace(">", "&gt;");
        ds = ds.replace("'","&apos;");
        ds = ds.replace("\"", "&quot;");
        ds = ds.replace("\r\n", "<w:br/>");
        ds = ds.replace("\n", "<w:br/>");
        // 删除控制字符
        ds = ds.replaceAll("\\p{Cntrl}", "");
        return ds;
    }

    /**
     * @author     : bruce lan/00001
     * @description: 判断字符串是否为整型
     * @date       : 2022-7-27 14:02
     * @return
     */
    public static boolean isInteger(String str) {
        try {
            Integer.parseInt(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static String convertToPinyin(String chineseName) {
        if(chineseName == null){
            return null;
        }
        StringBuilder pinyin = new StringBuilder();
        for (char c : chineseName.toCharArray()) {
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
            if (pinyinArray != null && pinyinArray.length > 0) {
                pinyin.append(pinyinArray[0]);
            } else {
                pinyin.append(c);
            }
        }
        return pinyin.toString().replaceAll("[^a-zA-Z]", "");
    }

    public static String getLastName(String pinyin) {
        // 姓氏只取第一个拼音
        return pinyin.substring(0, 1).toUpperCase();
    }

    public static String getFirstName(String pinyin, int chineseNameLength) {
        // 名字由除去姓氏之后的拼音组成
        return pinyin.substring(1).toLowerCase();
    }

    /**
     * 判断是否为中文
     * @param name
     * @return
     */
    public static boolean isChineseName(String name) {
        // 使用正则表达式匹配中文字符
        String regex = "[\\u4e00-\\u9fa5]+";
        Pattern pattern = Pattern.compile(regex);
        return pattern.matcher(name).matches();
    }

    // 去除HTML标签
    public static String removeHtmlTags(String htmlString) {
        // 使用正则表达式匹配并替换HTML标签
        Pattern pattern = Pattern.compile("<[^>]*>");
        Matcher matcher = pattern.matcher(htmlString);
        return matcher.replaceAll("");
    }

    /**
     * 随机生成 length 位的字符串，只包含大小写字母和数字（ABCDEFGHJKLMNPQRSTUVWXY0123456789）
     * @param length 字符串位数
     * @return 字符串
     */
    public static String generateRandomString(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            int index = RANDOM.nextInt(CHARACTERS.length());
            sb.append(CHARACTERS.charAt(index));
        }
        return sb.toString();
    }

}
